package com.sc.admin.core.xml.resolver;


import com.sc.admin.core.xml.XMLDefaultResolver;
import com.sc.common.entity.admin.lookup.SysLookup;
import com.sc.common.exception.BusinessException;
import com.sc.common.util.MyStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.core.io.ClassPathResource;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.*;

/**
 *
 * Function:
 * Reason:
 * Date:2018/6/27
 * @author wust
 */
public class XMLLookupResolver extends XMLDefaultResolver {

    static Logger logger = LogManager.getLogger(XMLLookupResolver.class);

    /**
     * 元素名称
     */
    private static final String ELEMENT_PATH = "path";
    private static final String ELEMENT_RECORD = "record";
    private static final String ELEMENT_CODE = "code";
    private static final String ELEMENT_PARENT_CODE = "parent_code";
    private static final String ELEMENT_ROOT_CODE = "root_code";
    private static final String ELEMENT_VALUE = "value";
    private static final String ELEMENT_NAME = "name";
    private static final String ELEMENT_STATUS = "status";
    private static final String ELEMENT_VISIBLE = "visible";
    private static final String ELEMENT_DESCRIPTION = "description";
    private static final String ELEMENT_SORT = "sort";

    private static final String ELEMENT_ATTRIBUTE_PATH = "path";

    private final Map<String, String> uniqueKeyCodeChecking = new HashMap<>();
    private List<SysLookup> sysLookups = new ArrayList<>();


    @Override
    public void parseXML() throws BusinessException {
        String mainXMLPath = "dictionary" + File.separator + "lookup" + File.separator + "main.xml";
        String mainXSDPath = "dictionary" + File.separator + "xsd" + File.separator + "main.xsd";
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        validateXML(mainXSDPath, mainXMLPath);

        try{
            ClassPathResource resource = new ClassPathResource(mainXMLPath);

            DocumentBuilder db = dbf.newDocumentBuilder();
            org.w3c.dom.Document doc = db.parse(resource.getInputStream());
            org.w3c.dom.Element element = doc.getDocumentElement();
            doParseXML(element, db, "");
        }catch (Exception e){
            throw new BusinessException(e);
        }
    }

    @Override
    public Map<String, List> getResult() {
        this.parseXML();

        Map<String, List> map = new HashMap<>(1);
        map.put("resultList",sysLookups);
        return map;
    }


    private void doParseXML(org.w3c.dom.Element element, DocumentBuilder db, String lang) throws Exception {
        NodeList children = element.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            short nodeType = node.getNodeType();
            if (nodeType == Node.ELEMENT_NODE) {
                if (ELEMENT_PATH.equals(node.getNodeName())) {
                    String path = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_ATTRIBUTE_PATH);
                    if (!StringUtils.isBlank(path) && !"*".equals(path)) {// 星号表示可以忽略的节点
                        String XMLPath = path;
                        /*String XSDPath = "dictionary" + File.separator + "xsd" + File.separator + "lookup.xsd";
                        super.validateXML(XSDPath, XMLPath);*/
                        org.w3c.dom.Document doc = db.parse(new ClassPathResource(XMLPath).getInputStream());
                        org.w3c.dom.Element subElement = doc.getDocumentElement();

                        if(path.indexOf('_') != -1){
                            lang = path.substring(path.indexOf('_') + 1, path.indexOf('.'));
                        }else{
                            lang = "zh_CN";
                        }

                        doParseXML(subElement, db, lang);
                    } else {
                        logger.info("属性path值为[" + path + "]，的节点忽略");
                    }
                }else if (ELEMENT_RECORD.equalsIgnoreCase(node.getNodeName())) {
                    String code = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_CODE);
                    String parentCode = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_PARENT_CODE);
                    String rootCode = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_ROOT_CODE);
                    String value = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_VALUE);
                    String name = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_NAME);
                    String status = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_STATUS);
                    String visible = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_VISIBLE);
                    String description = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_DESCRIPTION);
                    String sort = ((org.w3c.dom.Element) node).getAttribute(ELEMENT_SORT);

                    String uniqueKeyCode = "CODE" + code + "_" + lang;
                    if (uniqueKeyCodeChecking.containsKey(uniqueKeyCode)) {
                        throw new BusinessException("解析sys_lookup.xml失败，CODE元素值不允许重复[" + code + "]");
                    }
                    uniqueKeyCodeChecking.put(uniqueKeyCode, null);


                    SysLookup lookup = new SysLookup();
                    lookup.setCode(code);
                    lookup.setParentCode(MyStringUtils.isBlank(MyStringUtils.null2String(rootCode)) ? "0000" : parentCode);
                    lookup.setRootCode(MyStringUtils.isBlank(MyStringUtils.null2String(rootCode)) ? "0000" : rootCode);
                    lookup.setValue(value);
                    lookup.setName(name);
                    lookup.setStatus(MyStringUtils.isBlank(MyStringUtils.null2String(status)) ? "A100201" : status);
                    lookup.setSort(MyStringUtils.isBlank(sort) ? 0 : Integer.parseInt(sort));
                    lookup.setVisible(MyStringUtils.isBlank(visible) ? "A100701" : ("Y".equalsIgnoreCase(visible) ? "A100701" : "A100702"));
                    lookup.setDescription(description);
                    lookup.setLan(lang);
                    lookup.setCreateTime(new Date());
                    lookup.setIsDeleted(0);
                    this.sysLookups.add(lookup);
                }
                doParseXML((org.w3c.dom.Element) node,db,lang);
            }
        }
    }
}
